package cart

import (
	// "fmt"
	"strings"

	"mall/common/utils/pointy"
	enum "mall/service/backend/common/enum/promotion"
	"mall/service/forum/api/internal/biz/promotion"
	"mall/service/promotion/rpc/promotionclient"

	"github.com/shopspring/decimal"
	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

// PromotionUseHandler 使用活动优惠handler
type PromotionUseHandler struct {
	// 合成复用Next
	Next
}

// Do 使用活动优惠
func (h *PromotionUseHandler) Do(c *Context) (err error) {
	if !c.Resp.StockValid {
		return
	}

	if len(c.Resp.ActivityList) == 0 {
		return
	}

	// logx.Infow("使用活动优惠...")

	// 活动优惠总额
	var activityAmount decimal.Decimal
	for key, activity := range c.Resp.ActivityList {
		// 先假定活动不满足条件
		c.Resp.ActivityList[key].Status = nil
		// 互斥类型
		if activity.MutexType != nil && uint8(*activity.MutexType) == enum.PromotionMutexTypeOrder {
			if _, ok := c.MutexMap[*activity.MutexType]; ok {
				continue
			}

			c.MutexMap[*activity.MutexType] = map[uint64]int64{*activity.Id: 1}
		}

		instance := &promotion.Activity{}
		var checkScope bool
		if activity.ActivityType != nil {
			switch uint8(*activity.ActivityType) {
			case enum.PromotionActivityDiscount, enum.PromotionActivityMember: // 满减送、会员优惠
				instance.ConcreteBehavior = &promotion.ActivityDiscount{}
				if activity.ScopeType != nil && uint8(*activity.ScopeType) != enum.PromotionScopeAll {
					checkScope = true
				}
			case enum.PromotionActivitySeckill: // 秒杀
				instance.ConcreteBehavior = &promotion.ActivitySeckill{}
			case enum.PromotionActivityPackage: // 商品套餐
				instance.ConcreteBehavior = &promotion.ActivityPackage{}
			default:
				continue
			}
		}

		ctx := &promotion.Context{
			ActInfo:  activity,
			UserId:   c.UserId,
			UserRank: strings.ToLower(c.UserRank),
			GemRatio: c.GemRatio,
			MutexMap: c.MutexMap,
		}
		var err error
		if err = instance.CheckParams(ctx); err != nil {
			logx.Infow("PromotionUseHandler CheckParams err:", logx.Field("detail", err.Error()))
			// logrus.Info(fmt.Sprintf("PromotionUseHandler CheckParams err: %+v", err))
			continue
		}

		// 具体方法：校验活动是否正在进行
		if err = instance.CheckTimeRange(ctx); err != nil {
			logx.Infow("PromotionUseHandler CheckTimeRange err:", logx.Field("detail", err.Error()))
			// logrus.Info(fmt.Sprintf("PromotionUseHandler CheckTimeRange err: %+v", err))
			continue
		}

		if err = instance.CheckMemberRestriction(ctx); err != nil {
			logx.Infow("PromotionUseHandler CheckMemberRestriction err:", logx.Field("detail", err.Error()))
			// logrus.Info(fmt.Sprintf("PromotionUseHandler CheckMemberRestriction err: %+v", err))
			continue
		}

		// 具体方法：参与次数校验(同时扣减)
		// todo

		var skuIdMap map[uint64]uint64
		if checkScope {
			// 适用范围
			skuIdMap, err = h.checkScope(c, *ctx.ActInfo.Id, c.SkuScopeInfos)
			if err != nil {
				logx.Infow("PromotionUseHandler checkScope err:", logx.Field("detail", err.Error()))
				// logrus.Info(fmt.Sprintf("PromotionUseHandler checkScope err: %+v", err))
				continue
			}
		}

		pricingInfos, orderPricingInfos := h.initPricingInfos(c, skuIdMap)
		ctx.PricingInfos = pricingInfos
		ctx.OrderPricingInfos = orderPricingInfos

		// “抽象方法”：获取SKU定价信息
		if err = instance.GetPricingInfo(ctx); err != nil { // 可能根据 PricingInfos 应用的优惠，修正 OrderPricingInfos
			logx.Infow("PromotionUseHandler GetPricingInfo err:", logx.Field("detail", err.Error()))
			// logrus.Info(fmt.Sprintf("PromotionUseHandler GetPricingInfo err: %+v", err))
			continue
		}

		// “抽象方法”：获取订单定价信息
		if err = instance.GetOrderPricingInfo(ctx); err != nil { // 可能根据 OrderPricingInfos 应用的优惠，修正 PricingInfos
			logx.Infow("PromotionUseHandler GetOrderPricingInfo err:", logx.Field("detail", err.Error()))
			// logrus.Info(fmt.Sprintf("PromotionUseHandler GetOrderPricingInfo err: %+v", err))
			continue
		}

		// Todo: review

		var related int
		for k, info := range ctx.OrderPricingInfos {
			// logrus.Info(fmt.Sprintf("PromotionUseHandler GetOrderPricingInfo: %+v", info))

			if k == 0 {
				continue
			}

			if info.ActivityId == int64(*activity.Id) {
				if related == 0 && info.Status > 0 {
					related = 1
				}
				if related >= 0 && info.Status < 0 {
					related = -1
				}
			}

			// 未满足条件的
			if info.Status < 0 {
				c.Resp.ActivityList[key].Threshold = info.Threshold
				c.Resp.ActivityList[key].Margin = info.Margin
				if c.Resp.ActivityList[key].GroupModeText != nil {
					if tips := strings.Split(*c.Resp.ActivityList[key].GroupModeText, ","); len(tips) == 2 {
						tips[0] = strings.Replace(tips[0], "N", info.Threshold, 1)
						tips[1] = strings.Replace(tips[1], "M", info.Margin, 1)
						c.Resp.ActivityList[key].Tips = strings.Join(tips, " ")
					}
				}
			}

			// 已满足条件的
			if info.Status > 0 {
				c.Resp.ActivityList[key].Threshold = info.Threshold
				if c.Resp.ActivityList[key].GroupModeText != nil {
					if tips := strings.Split(*c.Resp.ActivityList[key].GroupModeText, ","); len(tips) == 2 {
						c.Resp.ActivityList[key].Tips =
							strings.Replace(tips[0], "N", info.Threshold, 1)
					}
				}
			}
		}

		// logrus.Info(fmt.Sprintf("PromotionUseHandler GetOrderPricingInfos: ==========\n"))

		for _, infos := range ctx.OrderPricingDetails {
			for _, info := range infos {
				// logrus.Info(fmt.Sprintf("%+v", info))

				c.Modifiers = append(c.Modifiers, &Modifier{
					ActivityId:     info.ActivityId,
					RuleId:         info.RuleId,
					ActivityAmount: info.ActivityAmount,
					Status:         info.Status,
					Effect:         info.Effect,
					EffectType:     info.EffectType,
					EffectValue:    info.EffectValue,
				})
				if info.Status > 0 {
					activityAmount = activityAmount.Add(info.ActivityAmount)
					c.FinalAmount = c.FinalAmount.Sub(info.ActivityAmount)
				}
			}
		}

		if related == 1 {
			c.Resp.ActivityList[key].Status = pointy.GetPointer(uint32(1))
		} else if related == -1 {
			c.Resp.ActivityList[key].Status = pointy.GetPointer(uint32(0))
		}

		// logrus.Info(fmt.Sprintf("============================================================\n"))
	}

	c.ActivityAmount = activityAmount

	return
}

func (h *PromotionUseHandler) checkScope(
	c *Context,
	activityId uint64,
	skuScopeInfos []*promotionclient.SkuScopeInfo,
) (skuIdMap map[uint64]uint64, err error) { // 返回每个sku适用的优惠活动
	res, err := c.SvcCtx.PromotionRpc.CheckActivityScope(c.Ctx, &promotionclient.CheckActivityScopeReq{
		ActivityId: activityId,
		Skus:       skuScopeInfos,
	})
	if err != nil {
		return nil, err
	}

	// logrus.Info(fmt.Sprintf("PromotionUseHandler CheckActivityScope res: %+v", res))

	if res.ActivityId == uint64(0) { // 全部商品
		return nil, nil
	}

	skuIdMap = make(map[uint64]uint64)
	if len(res.SkuIds) == 0 { // 没有商品
		return skuIdMap, nil
	}

	for _, skuId := range res.SkuIds {
		skuIdMap[skuId] = activityId
	}

	return skuIdMap, nil
}

func (h *PromotionUseHandler) initPricingInfos(
	c *Context,
	skuIdMap map[uint64]uint64,
) (pricingInfos []*promotion.PricingInfo, orderPricingInfos []*promotion.OrderPricingInfo) {
	var skusNumber int64
	var skusAmount decimal.Decimal
	for _, info := range c.PricingInfos {
		if skuIdMap != nil {
			if _, ok := skuIdMap[info.SkuId]; !ok {
				continue
			}
		}

		if info.Checked > 0 {
			skusNumber += info.SkuNumber
			skusAmount = skusAmount.Add(info.SkuAmount)
		}
		pricingInfos = append(pricingInfos, info)
	}

	orderPricingInfos = append(orderPricingInfos, &promotion.OrderPricingInfo{
		SkusNumber:  skusNumber,
		SkusAmount:  skusAmount,
		FinalAmount: c.FinalAmount,
	})

	return
}
